package org.zhadoop.streaming.common;

import java.math.BigDecimal;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zhadoop.streaming.exception.ErrorCode;
import org.zhadoop.streaming.exception.IllegalDataTypeException;

/**
 * 流处理中类型处理工具类 功能详细描述
 * 
 * @author zwd
 *
 */
public class StreamClassUtil {
	private static final int COUNT_INT = 2;

	private static final Logger LOG = LoggerFactory.getLogger(StreamClassUtil.class);

	/**
	 * 返回包装类
	 * 
	 * @param type
	 * @return
	 */
	public static Class<?> getWrapType(Class<?> type) {
		if (!type.isPrimitive()) {
			return type;
		}

		if (type == boolean.class) {
			return Boolean.class;
		}

		if (type == int.class) {
			return Integer.class;
		}

		if (type == long.class) {
			return Long.class;
		}

		if (type == double.class) {
			return Double.class;
		}

		if (type == float.class) {
			return Float.class;
		}

		return type;
	}

	/**
	 * <判断是否数字类型> <功能详细描述>
	 *
	 */
	public static boolean isNumberic(Class<?> type) {
		if ((type == Double.class) || (type == double.class)) {
			return true;
		}

		if ((type == Float.class) || (type == float.class)) {
			return true;
		}

		if ((type == Long.class) || (type == long.class)) {
			return true;
		}

		if ((type == Integer.class) || (type == int.class)) {
			return true;
		}

		if (type == BigDecimal.class) {
			return true;
		}

		return false;
	}

	/**
	 * 根据算术运算的左右表达式类型，推测结果类型
	 * 
	 * @param leftType
	 * @param rightType
	 * @return
	 */
	public static Class<?> getArithmaticType(Class<?> leftType, Class<?> rightType) throws IllegalDataTypeException {
		Class<?> leftWarp = getWrapType(leftType);
		Class<?> rightWarp = getWrapType(rightType);

		if (!isNumberic(leftType) || isNumberic(rightType)) {
			LOG.error("Can't infer result type from {} and {}.", leftType.getName(), rightType.getName());
			IllegalDataTypeException exp = new IllegalDataTypeException(
					ErrorCode.SEMANTICANALYZE_ARITHMETIC_EXPRESSION_NUMBER_TYPE);
			throw exp;
		}

		if (leftWarp == rightWarp) {
			return leftWarp;
		}

		if ((leftWarp == BigDecimal.class) || (rightWarp == BigDecimal.class)) {
			return leftWarp;
		}
		if (leftWarp == Double.class || rightWarp == Double.class) {
			return Double.class;
		}

		if (leftWarp == Float.class || rightWarp == Float.class) {
			return Float.class;
		}

		if (leftWarp == Long.class || rightWarp == Long.class) {
			return Long.class;
		}

		return Integer.class;
	}

}
